/**
 * LoginTemplate.java
 * @author taowei20061122@163.com
 * 2013-6-14 下午1:04:00
 */
package study.designpattern.templatemethod;


import study.designpattern.templatemethod.bean.LoginModel;

/**
 * 登录控制的模板
 * 
 * 场景问题：登录控制，普通用户和工作人员是存放在不同的表里面的，也是不同的模块来维护的；
 *     另外工作人员的密码加密的。
 * 解决方案：模板方法模式：定义一个操作中的算法的骨架，而将一些操作延迟到子类中。使得子类
 *     可以不改变一个算法的结构即可重定义算法的某些特定步骤。
 *     
 *模板方法模式的本质：固定算法骨架
 *何时选用模板方法模式：
 *    1.需要固定算法骨架，实现一个算法的不变的部分，并把可变的行为留给子类来实现的情况；
 *    2.各个子类中具有公共行为，应该抽取出来，集中在一个公共类中去实现，从而避免代码重复；
 *    3.需要控制子类扩展的情况。模板方法模式会在特定的点来调用子类的方法，这样只允许在这些点进行扩展；
 * @author taowei20061122@163.com
 * 2013-6-14 下午1:04:00
 */
public abstract class LoginTemplate {
	/**
	 * 根据登录编号来查找和获取相应的数据 （原语操作，需要子类实现）
	 * @param loginId
	 * @return
	 */
	public abstract LoginModel findLoginUser(String loginId);
	/**
	 * 对密码数据进行加密 （钩子方法，父类提供的默认实现，子类可以覆盖）
	 * @param pwd
	 * @return
	 */
	public String encryptPwd(String pwd) {
		return pwd;
	}
	/**
	 * 判断用户填写的数据与数据库中存储的数据是否一致 （钩子方法，父类提供的默认实现，子类可以覆盖）
	 * @param lm  用户填写的数据
	 * @param dbLm  数据库中存储的数据
	 * @return  true-匹配成功，false-匹配失败
	 */
	public boolean match(LoginModel lm, LoginModel dbLm) {
		boolean flag = false;
		if (lm.getLoginId().equals(dbLm.getLoginId()) && lm.getPwd().equals(dbLm.getPwd())) {
			flag = true;
		}
		return flag;
	}
	/**
	 * 判断登录数据是否正确  （模板方法，定义算法骨架）
	 * @param loginModel  封装登录数据的模型
	 * @return true-登录成功，false-登录失败
	 */
	public final boolean login(LoginModel loginModel) {
		boolean flag = false;
		//1.根据登录人员的编号去获取相应的数据
		LoginModel dbLm = this.findLoginUser(loginModel.getLoginId());		
		if (dbLm!=null) {
			//2.对密码进行加密
			String encryptPwd = this.encryptPwd(loginModel.getPwd());
			//把加密后的密码设置回登录的数据模型中
			loginModel.setPwd(encryptPwd);
			//3.判断是否匹配
			flag = this.match(loginModel, dbLm);
		}
		return flag;
	}
}
